package com.study.lib_tiandi_map.utils

import com.study.lib_tiandi_map.interfaces.Point
import com.study.lib_tiandi_map.utils.transform.GisCheckUtils
import com.study.lib_tiandi_map.utils.transform.LatLon
import com.study.lib_tiandi_map.utils.transform.SegmentLatLon
import kotlin.math.acos
import kotlin.math.cos
import kotlin.math.sin

object MapUtils {

    private const val EARTH_RADIUS = 6371393 // 地球平均半径,单位：m

    /**
     * 计算一个坐标点是否在一个平面的内部
     */
    fun isPolygonContainsPoint(polygonPoints: List<Point>, point: Point): Boolean {
        return if (polygonPoints.isNotEmpty()) {
            var var2 = 0
            while (var2 < polygonPoints.size) {
                if (point.lng == (polygonPoints[var2]).lng && point.lat == (polygonPoints[var2]).lat) {
                    return true
                }
                ++var2
            }
            var2 = 0
            var var4: Point?
            var var5: Point?
            var var6: Double
            val var8 = polygonPoints.size
            for (var9 in 0 until var8) {
                var4 = polygonPoints[var9]
                var5 = polygonPoints[(var9 + 1) % var8]
                if (var4.lat != var5.lat && point.lat >= var4.lat.coerceAtMost(var5.lat) && point.lat < var4.lat.coerceAtLeast(
                        var5.lat
                    )
                ) {
                    var6 =
                        (point.lat - var4.lat) * (var5.lng - var4.lng) / (var5.lat - var4.lat) + var4.lng
                    if (var6 == point.lng) {
                        return true
                    }
                    if (var6 < point.lng) {
                        ++var2
                    }
                }
            }
            var2 % 2 == 1
        } else {
            false
        }
    }

    /**
     * 判断点的集合连接成的多边形是否相交
     */
    fun isCross(points: List<Point>): Boolean {
        if (points.size <= 3) {
            return false
        }
        //定义线段，目前的多边形有多少条线段
        val segments = mutableListOf<SegmentLatLon>()
        points.forEachIndexed { index, point ->
            if (index < points.size - 1) {
                val startPoint = LatLon(point.lng, point.lat)
                val endPoint = LatLon(points[index + 1].lng, points[index + 1].lat)
                segments.add(SegmentLatLon(startPoint, endPoint))
            } else {
                val startPoint = LatLon(points[points.size - 1].lng, points[points.size - 1].lat)
                val endPoint = LatLon(points[0].lng, points[0].lat)
                segments.add(SegmentLatLon(startPoint, endPoint))
            }

        }
//测试打印
//        for (point in points) {
//            Log.e("打印测试", "lat:${point.lat} lng:${point.lng}")
//        }
//        for (s in segments) {
//            Log.e("打印测试", "startLat:${s.startLatLon.lat} startLng:${s.startLatLon.lon}")
//            Log.e("打印测试", "endLat:${s.endLatLon.lat} endLng:${s.endLatLon.lon}")
//        }

        //判断线段是否相交
        for (i in 0 until segments.size - 1) {
            for (j in i + 1 until segments.size) {
                if (j - i == 1) {
                    continue
                }
                if (i == 0 && j == segments.size - 1) {
                    continue
                }
                //是否相交
                val isCross = GisCheckUtils.segIntersect(segments[i], segments[j])
                //交点
//                val crossPoint = GisCheckUtils.getIntersectPoint(segments[i], segments[j])
                if (isCross) {
                    return true
                }
            }
        }
        return false
    }

    /**
     * 通过AB点经纬度获取距离
     *
     * @param pointA A点(经，纬)
     * @param pointB B点(经，纬)
     * @return 距离(单位：米)
     */
    fun getDistance(pointA: Point, pointB: Point): Double {
        // 经纬度（角度）转弧度。弧度用作参数，以调用Math.cos和Math.sin
        val radiansAX = Math.toRadians(pointA.lng) // A经弧度
        val radiansAY = Math.toRadians(pointA.lat) // A纬弧度
        val radiansBX = Math.toRadians(pointB.lng) // B经弧度
        val radiansBY = Math.toRadians(pointB.lat) // B纬弧度

        // cosβ1cosβ2cos（α1-α2）+sinβ1sinβ2
        val cos = cos(radiansAY) * cos(radiansBY) *
                cos(radiansAX - radiansBX) + sin(radiansAY) * sin(radiansBY)
        val aCos = acos(cos); // 反余弦值
        return EARTH_RADIUS * aCos // 最终结果
    }

    /**
     * 计算最接的地图缩放比例
     */
    fun getBestZoom(maxLat: Double, maxLon: Double, minLat: Double, minLon: Double): Int {
        return when (getDistance(
            pointA = Point(lng = maxLon, lat = maxLat),
            pointB = Point(lng = minLon, lat = minLat)
        )) {
            in 0f..500f -> 18
            in 500f..1000f -> 17
            in 1000f..2000f -> 16
            in 2000f..5000f -> 15
            else -> 14
        }
    }
}